1 /* xscreensaver, Copyright (c) 1992-2008 Jamie Zawinski <jwz@jwz.org>
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
11 * This code derived from TI Explorer Lisp code by Joe Keane, Fritz Mueller,
16 #include "screenhack.h"
18 #define POINT_COUNT 16
21 #define ANGLE_SCALE 0.001
45 float hs_two_observer_z;
60 double hs_cos_xy, hs_sin_xy;
61 double hs_cos_xz, hs_sin_xz;
62 double hs_cos_yz, hs_sin_yz;
63 double hs_cos_xw, hs_sin_xw;
64 double hs_cos_yw, hs_sin_yw;
65 double hs_cos_zw, hs_sin_zw;
66 double hs_ref_ax, hs_ref_ay, hs_ref_az, hs_ref_aw;
67 double hs_ref_bx, hs_ref_by, hs_ref_bz, hs_ref_bw;
68 double hs_ref_cx, hs_ref_cy, hs_ref_cz, hs_ref_cw;
69 double hs_ref_dx, hs_ref_dy, hs_ref_dz, hs_ref_dw;
70 struct point_state hs_points[POINT_COUNT];
74 static const struct line_info line_table[LINE_COUNT];
76 static const char *hypercube_defaults[] =
101 static XrmOptionDescRec hypercube_options [] =
103 { "-color0", ".color0", XrmoptionSepArg, 0 },
104 { "-color1", ".color1", XrmoptionSepArg, 0 },
105 { "-color2", ".color2", XrmoptionSepArg, 0 },
106 { "-color3", ".color3", XrmoptionSepArg, 0 },
107 { "-color4", ".color4", XrmoptionSepArg, 0 },
108 { "-color5", ".color5", XrmoptionSepArg, 0 },
109 { "-color6", ".color6", XrmoptionSepArg, 0 },
110 { "-color7", ".color7", XrmoptionSepArg, 0 },
112 { "-xw", ".xw", XrmoptionSepArg, 0 },
113 { "-xy", ".xy", XrmoptionSepArg, 0 },
114 { "-xz", ".xz", XrmoptionSepArg, 0 },
115 { "-yw", ".yw", XrmoptionSepArg, 0 },
116 { "-yz", ".yz", XrmoptionSepArg, 0 },
117 { "-zw", ".zw", XrmoptionSepArg, 0 },
119 { "-observer-z", ".observer-z", XrmoptionSepArg, 0 },
120 { "-delay", ".delay", XrmoptionSepArg, 0 },
125 static void set_sizes (struct hyper_state *hs, int width, int height);
128 hypercube_init (Display *dpy, Window win)
132 unsigned long bg_pixel;
136 struct hyper_state *hs = (struct hyper_state *) calloc (1, sizeof(*hs));
137 hs->hs_display = dpy;
140 observer_z = get_float_resource (dpy, "observer-z", "Float");
141 if (observer_z < 1.125)
143 /* hs->hs_observer_z = observer_z; */
144 hs->hs_two_observer_z = 2.0 * observer_z;
147 XWindowAttributes wa;
148 XGetWindowAttributes (dpy, win, &wa);
150 set_sizes (hs, wa.width, wa.height);
153 delay = get_integer_resource (dpy, "delay", "Integer");
154 hs->hs_delay = delay;
156 bg_pixel = get_pixel_resource (dpy, cmap, "background", "Background");
161 unsigned long fg_pixel;
164 gcv.function = GXcopy;
165 gcv.foreground = bg_pixel;
166 black_gc = XCreateGC (dpy, win, GCForeground|GCFunction, &gcv);
167 fg_pixel = get_pixel_resource (dpy, cmap, "foreground", "Foreground");
168 gcv.foreground = fg_pixel ^ bg_pixel;
169 white_gc = XCreateGC (dpy, win, GCForeground|GCFunction, &gcv);
170 hs->hs_color_gcs[0] = black_gc;
171 hs->hs_color_gcs[1] = white_gc;
177 gcv.function = GXcopy;
179 gcv.foreground = get_pixel_resource (dpy, cmap,
180 "background", "Background");
181 hs->black_gc = XCreateGC (dpy, win, GCForeground|GCFunction, &gcv);
183 for (col = 0; col < 8; col++)
186 unsigned long fg_pixel;
189 sprintf (buffer, "color%d", col);
190 fg_pixel = get_pixel_resource (dpy, cmap, buffer, "Foreground");
191 gcv.foreground = fg_pixel;
192 color_gc = XCreateGC (dpy, win, GCForeground|GCFunction, &gcv);
193 hs->hs_color_gcs[col] = color_gc;
197 hs->hs_ref_ax = 1.0, hs->hs_ref_ay = 0.0, hs->hs_ref_az = 0.0, hs->hs_ref_aw = 0.0;
198 hs->hs_ref_bx = 0.0, hs->hs_ref_by = 1.0, hs->hs_ref_bz = 0.0, hs->hs_ref_bw = 0.0;
199 hs->hs_ref_cx = 0.0, hs->hs_ref_cy = 0.0, hs->hs_ref_cz = 1.0, hs->hs_ref_cw = 0.0;
200 hs->hs_ref_dx = 0.0, hs->hs_ref_dy = 0.0, hs->hs_ref_dz = 0.0, hs->hs_ref_dw = 1.0;
209 double cos_xy, sin_xy;
210 double cos_xz, sin_xz;
211 double cos_yz, sin_yz;
212 double cos_xw, sin_xw;
213 double cos_yw, sin_yw;
214 double cos_zw, sin_zw;
216 xy = get_float_resource (dpy, "xy", "Float") * ANGLE_SCALE;
217 xz = get_float_resource (dpy, "xz", "Float") * ANGLE_SCALE;
218 yz = get_float_resource (dpy, "yz", "Float") * ANGLE_SCALE;
219 xw = get_float_resource (dpy, "xw", "Float") * ANGLE_SCALE;
220 yw = get_float_resource (dpy, "yw", "Float") * ANGLE_SCALE;
221 zw = get_float_resource (dpy, "zw", "Float") * ANGLE_SCALE;
223 cos_xy = cos (xy), sin_xy = sin (xy);
224 hs->hs_cos_xy = cos_xy, hs->hs_sin_xy = sin_xy;
225 cos_xz = cos (xz), sin_xz = sin (xz);
226 hs->hs_cos_xz = cos_xz, hs->hs_sin_xz = sin_xz;
227 cos_yz = cos (yz), sin_yz = sin (yz);
228 hs->hs_cos_yz = cos_yz, hs->hs_sin_yz = sin_yz;
229 cos_xw = cos (xw), sin_xw = sin (xw);
230 hs->hs_cos_xw = cos_xw, hs->hs_sin_xw = sin_xw;
231 cos_yw = cos (yw), sin_yw = sin (yw);
232 hs->hs_cos_yw = cos_yw, hs->hs_sin_yw = sin_yw;
233 cos_zw = cos (zw), sin_zw = sin (zw);
234 hs->hs_cos_zw = cos_zw, hs->hs_sin_zw = sin_zw;
242 hypercube_draw (Display *dpy, Window window, void *closure)
244 struct hyper_state *hs = (struct hyper_state *) closure;
245 int this_delay = hs->hs_delay;
247 #ifdef HAVE_COCOA /* Don't second-guess Quartz's double-buffering */
248 XClearWindow (dpy, window);
254 char moved[POINT_COUNT];
260 resize = hs->hs_resize;
261 if (icon || !(hs->roted | resize))
269 double az, bz, cz, dz;
271 double ax, bx, cx, dx;
273 double ay, by, cy, dy;
275 struct point_state *ps;
286 #define compute(as,bs,cs,ds,i) \
287 az = hs->hs_ref_az; bz = hs->hs_ref_bz; cz = hs->hs_ref_cz; dz = hs->hs_ref_dz; \
288 ax = hs->hs_ref_ax; bx = hs->hs_ref_bx; cx = hs->hs_ref_cx; dx = hs->hs_ref_dx; \
289 ay = hs->hs_ref_ay; by = hs->hs_ref_by; cy = hs->hs_ref_cy; dy = hs->hs_ref_dy; \
290 sum_z = as az bs bz cs cz ds dz; \
291 observer_z = hs->hs_two_observer_z; \
292 unit_scale = hs->hs_unit_scale; \
293 sum_x = as ax bs bx cs cx ds dx; \
294 sum_y = as ay bs by cs cy ds dy; \
295 ps = &hs->hs_points[i]; \
296 mul = unit_scale / (observer_z - sum_z); \
297 offset_x = hs->hs_offset_x; \
298 offset_y = hs->hs_offset_y; \
301 xf = sum_x * mul + offset_x; \
302 yf = sum_y * mul + offset_y; \
303 new_x = (int)rint(xf); \
304 new_y = (int)rint(yf); \
309 mov = old_x != new_x || old_y != new_y; \
312 compute (-, -, -, -, 0);
313 compute (-, -, -, +, 1);
314 compute (-, -, +, -, 2);
315 compute (-, -, +, +, 3);
316 compute (-, +, -, -, 4);
317 compute (-, +, -, +, 5);
318 compute (-, +, +, -, 6);
319 compute (-, +, +, +, 7);
320 compute (+, -, -, -, 8);
321 compute (+, -, -, +, 9);
322 compute (+, -, +, -, 10);
323 compute (+, -, +, +, 11);
324 compute (+, +, -, -, 12);
325 compute (+, +, -, +, 13);
326 compute (+, +, +, -, 14);
327 compute (+, +, +, +, 15);
332 redraw = hs->hs_redraw;
333 if (icon || !(hs->roted | redraw))
338 const struct line_info *lip;
343 lip = &line_table[0];
352 struct point_state *sp;
353 struct point_state *sq;
369 if (!(redraw | mov_p | mov_q))
372 sp = &hs->hs_points[ip];
373 sq = &hs->hs_points[iq];
377 erase_gc = hs->hs_color_gcs[0];
378 draw_gc = hs->hs_color_gcs[1];
382 erase_gc = hs->black_gc;
383 draw_gc = hs->hs_color_gcs[col];
392 XDrawLine (dpy, win, erase_gc, p_x, p_y, q_x, q_y);
399 XDrawLine (dpy, win, draw_gc, p_x, p_y, q_x, q_y);
419 /* If you get error messages about the following forms, and you think you're
420 using an ANSI C conforming compiler, then you're mistaken. Possibly you're
421 mixing an ANSI compiler with a non-ANSI preprocessor, or vice versa.
422 Regardless, your system is broken; it's not a bug in this program.
424 #if defined(__STDC__) || defined(__ANSI_CPP__)
426 #define rotate(name,dim0,dim1) \
427 old_u = hs->hs_ref_##name##dim0; \
428 old_v = hs->hs_ref_##name##dim1; \
429 new_u = old_u * cos_a + old_v * sin_a; \
430 new_v = old_v * cos_a - old_u * sin_a; \
431 hs->hs_ref_##name##dim0 = new_u; \
432 hs->hs_ref_##name##dim1 = new_v;
434 #define rotates(dim0,dim1) \
435 if (hs->hs_sin_##dim0##dim1 != 0) { \
436 cos_a = hs->hs_cos_##dim0##dim1; \
437 sin_a = hs->hs_sin_##dim0##dim1; \
438 rotate(a,dim0,dim1); \
439 rotate(b,dim0,dim1); \
440 rotate(c,dim0,dim1); \
441 rotate(d,dim0,dim1); \
444 #else /* !__STDC__, courtesy of Andreas Luik <luik@isa.de> */
446 #define rotate(name,dim0,dim1) \
447 old_u = hs->hs_ref_/**/name/**/dim0; \
448 old_v = hs->hs_ref_/**/name/**/dim1; \
449 new_u = old_u * cos_a + old_v * sin_a; \
450 new_v = old_v * cos_a - old_u * sin_a; \
451 hs->hs_ref_/**/name/**/dim0 = new_u; \
452 hs->hs_ref_/**/name/**/dim1 = new_v;
454 #define rotates(dim0,dim1) \
455 if (hs->hs_sin_/**/dim0/**/dim1 != 0) { \
456 cos_a = hs->hs_cos_/**/dim0/**/dim1; \
457 sin_a = hs->hs_sin_/**/dim0/**/dim1; \
458 rotate(a,dim0,dim1); \
459 rotate(b,dim0,dim1); \
460 rotate(c,dim0,dim1); \
461 rotate(d,dim0,dim1); \
464 #endif /* !__STDC__ */
475 /* stop = hs->hs_stop; */
476 delay = hs->hs_delay;
477 if (stop && this_delay < 10000)
485 hypercube_event (Display *dpy, Window window, void *closure, XEvent *e)
487 struct hyper_state *hs = (struct hyper_state *) closure;
488 if (e->type == ButtonPress && e->xbutton.button == 2)
490 hs->hs_stop = !hs->hs_stop;
497 hypercube_reshape (Display *dpy, Window window, void *closure,
498 unsigned int w, unsigned int h)
500 struct hyper_state *hs = (struct hyper_state *) closure;
501 set_sizes (hs, w, h);
502 XClearWindow (dpy, window);
507 set_sizes (struct hyper_state *hs, int width, int height)
516 observer_z = 0.5 * hs->hs_two_observer_z;
517 min_dim = width < height ? width : height;
518 var = sqrt(observer_z * observer_z - 1.0);
519 offset_x = 0.5 * (double)(width - 1);
520 offset_y = 0.5 * (double)(height - 1);
521 unit_scale = 0.4 * min_dim * var;
522 hs->hs_offset_x = (float)offset_x;
523 hs->hs_offset_y = (float)offset_y;
524 hs->hs_unit_scale = (float)unit_scale;
530 static const struct line_info line_table[LINE_COUNT] =
567 hypercube_free (Display *dpy, Window window, void *closure)
571 XSCREENSAVER_MODULE ("HyperCube", hypercube)