1 /* xscreensaver, Copyright (c) 1992, 1995, 1996, 1998, 2000
2 * Jamie Zawinski <jwz@jwz.org>
4 * Permission to use, copy, modify, distribute, and sell this software and its
5 * documentation for any purpose is hereby granted without fee, provided that
6 * the above copyright notice appear in all copies and that both that
7 * copyright notice and this permission notice appear in supporting
8 * documentation. No representations are made about the suitability of this
9 * software for any purpose. It is provided "as is" without express or
12 * This code derived from TI Explorer Lisp code by Joe Keane, Fritz Mueller,
17 #include "screenhack.h"
19 #define POINT_COUNT 16
22 #define ANGLE_SCALE 0.001
46 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];
73 static const struct line_info line_table[LINE_COUNT];
75 static void init (struct hyper_state *hs);
76 static void hyper (struct hyper_state *hs);
77 static void check_events (struct hyper_state *hs);
78 static void set_sizes (struct hyper_state *hs, int width, int height);
80 static struct hyper_state hyper_state;
83 char *progclass = "Hypercube";
109 XrmOptionDescRec options [] =
111 { "-color0", ".color0", XrmoptionSepArg, 0 },
112 { "-color1", ".color1", XrmoptionSepArg, 0 },
113 { "-color2", ".color2", XrmoptionSepArg, 0 },
114 { "-color3", ".color3", XrmoptionSepArg, 0 },
115 { "-color4", ".color4", XrmoptionSepArg, 0 },
116 { "-color5", ".color5", XrmoptionSepArg, 0 },
117 { "-color6", ".color6", XrmoptionSepArg, 0 },
118 { "-color7", ".color7", XrmoptionSepArg, 0 },
120 { "-xw", ".xw", XrmoptionSepArg, 0 },
121 { "-xy", ".xy", XrmoptionSepArg, 0 },
122 { "-xz", ".xz", XrmoptionSepArg, 0 },
123 { "-yw", ".yw", XrmoptionSepArg, 0 },
124 { "-yz", ".yz", XrmoptionSepArg, 0 },
125 { "-zw", ".zw", XrmoptionSepArg, 0 },
127 { "-observer-z", ".observer-z", XrmoptionSepArg, 0 },
128 { "-delay", ".delay", XrmoptionSepArg, 0 },
134 screenhack (Display *d, Window w)
136 struct hyper_state *hs;
149 init (struct hyper_state *hs)
155 unsigned long bg_pixel;
159 dpy = hs->hs_display;
162 observer_z = get_float_resource ("observer-z", "Float");
163 if (observer_z < 1.125)
165 /* hs->hs_observer_z = observer_z; */
166 hs->hs_two_observer_z = 2.0 * observer_z;
170 XWindowAttributes wa;
174 root = get_boolean_resource("root", "Boolean");
175 XGetWindowAttributes (dpy, win, &wa);
176 XSelectInput(dpy, win, root ? ExposureMask :
177 wa.your_event_mask | ExposureMask |
178 ButtonPressMask | StructureNotifyMask);
183 set_sizes (hs, width, height);
186 delay = get_integer_resource ("delay", "Integer");
187 hs->hs_delay = delay;
189 bg_pixel = get_pixel_resource ("background", "Background", dpy, cmap);
194 unsigned long fg_pixel;
197 gcv.function = GXcopy;
198 gcv.foreground = bg_pixel;
199 black_gc = XCreateGC (dpy, win, GCForeground|GCFunction, &gcv);
200 fg_pixel = get_pixel_resource ("foreground", "Foreground", dpy, cmap);
201 gcv.foreground = fg_pixel ^ bg_pixel;
202 white_gc = XCreateGC (dpy, win, GCForeground|GCFunction, &gcv);
203 hs->hs_color_gcs[0] = black_gc;
204 hs->hs_color_gcs[1] = white_gc;
210 gcv.function = GXxor;
211 for (col = 0; col < 8; col++)
214 unsigned long fg_pixel;
217 sprintf (buffer, "color%d", col);
218 fg_pixel = get_pixel_resource (buffer, "Foreground", dpy, cmap);
219 gcv.foreground = fg_pixel ^ bg_pixel;
220 color_gc = XCreateGC (dpy, win, GCForeground|GCFunction, &gcv);
221 hs->hs_color_gcs[col] = color_gc;
225 hs->hs_ref_ax = 1.0, hs->hs_ref_ay = 0.0, hs->hs_ref_az = 0.0, hs->hs_ref_aw = 0.0;
226 hs->hs_ref_bx = 0.0, hs->hs_ref_by = 1.0, hs->hs_ref_bz = 0.0, hs->hs_ref_bw = 0.0;
227 hs->hs_ref_cx = 0.0, hs->hs_ref_cy = 0.0, hs->hs_ref_cz = 1.0, hs->hs_ref_cw = 0.0;
228 hs->hs_ref_dx = 0.0, hs->hs_ref_dy = 0.0, hs->hs_ref_dz = 0.0, hs->hs_ref_dw = 1.0;
237 double cos_xy, sin_xy;
238 double cos_xz, sin_xz;
239 double cos_yz, sin_yz;
240 double cos_xw, sin_xw;
241 double cos_yw, sin_yw;
242 double cos_zw, sin_zw;
244 xy = get_float_resource ("xy", "Float") * ANGLE_SCALE;
245 xz = get_float_resource ("xz", "Float") * ANGLE_SCALE;
246 yz = get_float_resource ("yz", "Float") * ANGLE_SCALE;
247 xw = get_float_resource ("xw", "Float") * ANGLE_SCALE;
248 yw = get_float_resource ("yw", "Float") * ANGLE_SCALE;
249 zw = get_float_resource ("zw", "Float") * ANGLE_SCALE;
251 cos_xy = cos (xy), sin_xy = sin (xy);
252 hs->hs_cos_xy = cos_xy, hs->hs_sin_xy = sin_xy;
253 cos_xz = cos (xz), sin_xz = sin (xz);
254 hs->hs_cos_xz = cos_xz, hs->hs_sin_xz = sin_xz;
255 cos_yz = cos (yz), sin_yz = sin (yz);
256 hs->hs_cos_yz = cos_yz, hs->hs_sin_yz = sin_yz;
257 cos_xw = cos (xw), sin_xw = sin (xw);
258 hs->hs_cos_xw = cos_xw, hs->hs_sin_xw = sin_xw;
259 cos_yw = cos (yw), sin_yw = sin (yw);
260 hs->hs_cos_yw = cos_yw, hs->hs_sin_yw = sin_yw;
261 cos_zw = cos (zw), sin_zw = sin (zw);
262 hs->hs_cos_zw = cos_zw, hs->hs_sin_zw = sin_zw;
268 hyper (struct hyper_state *hs)
278 char moved[POINT_COUNT];
286 resize = hs->hs_resize;
287 if (icon || !(roted | resize))
295 double az, bz, cz, dz;
297 double ax, bx, cx, dx;
299 double ay, by, cy, dy;
301 struct point_state *ps;
312 #define compute(as,bs,cs,ds,i) \
313 az = hs->hs_ref_az; bz = hs->hs_ref_bz; cz = hs->hs_ref_cz; dz = hs->hs_ref_dz; \
314 ax = hs->hs_ref_ax; bx = hs->hs_ref_bx; cx = hs->hs_ref_cx; dx = hs->hs_ref_dx; \
315 ay = hs->hs_ref_ay; by = hs->hs_ref_by; cy = hs->hs_ref_cy; dy = hs->hs_ref_dy; \
316 sum_z = as az bs bz cs cz ds dz; \
317 observer_z = hs->hs_two_observer_z; \
318 unit_scale = hs->hs_unit_scale; \
319 sum_x = as ax bs bx cs cx ds dx; \
320 sum_y = as ay bs by cs cy ds dy; \
321 ps = &hs->hs_points[i]; \
322 mul = unit_scale / (observer_z - sum_z); \
323 offset_x = hs->hs_offset_x; \
324 offset_y = hs->hs_offset_y; \
327 xf = sum_x * mul + offset_x; \
328 yf = sum_y * mul + offset_y; \
329 new_x = (int)rint(xf); \
330 new_y = (int)rint(yf); \
335 mov = old_x != new_x || old_y != new_y; \
338 compute (-, -, -, -, 0);
339 compute (-, -, -, +, 1);
340 compute (-, -, +, -, 2);
341 compute (-, -, +, +, 3);
342 compute (-, +, -, -, 4);
343 compute (-, +, -, +, 5);
344 compute (-, +, +, -, 6);
345 compute (-, +, +, +, 7);
346 compute (+, -, -, -, 8);
347 compute (+, -, -, +, 9);
348 compute (+, -, +, -, 10);
349 compute (+, -, +, +, 11);
350 compute (+, +, -, -, 12);
351 compute (+, +, -, +, 13);
352 compute (+, +, +, -, 14);
353 compute (+, +, +, +, 15);
358 redraw = hs->hs_redraw;
359 if (icon || !(roted | redraw))
364 const struct line_info *lip;
370 lip = &line_table[0];
372 dpy = hs->hs_display;
380 struct point_state *sp;
381 struct point_state *sq;
397 if (!(redraw | mov_p | mov_q))
400 sp = &hs->hs_points[ip];
401 sq = &hs->hs_points[iq];
405 erase_gc = hs->hs_color_gcs[0];
406 draw_gc = hs->hs_color_gcs[1];
412 color_gc = hs->hs_color_gcs[col];
423 XDrawLine (dpy, win, erase_gc, p_x, p_y, q_x, q_y);
430 XDrawLine (dpy, win, draw_gc, p_x, p_y, q_x, q_y);
452 /* If you get error messages about the following forms, and you think you're
453 using an ANSI C conforming compiler, then you're mistaken. Possibly you're
454 mixing an ANSI compiler with a non-ANSI preprocessor, or vice versa.
455 Regardless, your system is broken; it's not a bug in this program.
457 #if defined(__STDC__) || defined(__ANSI_CPP__)
459 #define rotate(name,dim0,dim1) \
460 old_u = hs->hs_ref_##name##dim0; \
461 old_v = hs->hs_ref_##name##dim1; \
462 new_u = old_u * cos_a + old_v * sin_a; \
463 new_v = old_v * cos_a - old_u * sin_a; \
464 hs->hs_ref_##name##dim0 = new_u; \
465 hs->hs_ref_##name##dim1 = new_v;
467 #define rotates(dim0,dim1) \
468 if (hs->hs_sin_##dim0##dim1 != 0) { \
469 cos_a = hs->hs_cos_##dim0##dim1; \
470 sin_a = hs->hs_sin_##dim0##dim1; \
471 rotate(a,dim0,dim1); \
472 rotate(b,dim0,dim1); \
473 rotate(c,dim0,dim1); \
474 rotate(d,dim0,dim1); \
477 #else /* !__STDC__, courtesy of Andreas Luik <luik@isa.de> */
479 #define rotate(name,dim0,dim1) \
480 old_u = hs->hs_ref_/**/name/**/dim0; \
481 old_v = hs->hs_ref_/**/name/**/dim1; \
482 new_u = old_u * cos_a + old_v * sin_a; \
483 new_v = old_v * cos_a - old_u * sin_a; \
484 hs->hs_ref_/**/name/**/dim0 = new_u; \
485 hs->hs_ref_/**/name/**/dim1 = new_v;
487 #define rotates(dim0,dim1) \
488 if (hs->hs_sin_/**/dim0/**/dim1 != 0) { \
489 cos_a = hs->hs_cos_/**/dim0/**/dim1; \
490 sin_a = hs->hs_sin_/**/dim0/**/dim1; \
491 rotate(a,dim0,dim1); \
492 rotate(b,dim0,dim1); \
493 rotate(c,dim0,dim1); \
494 rotate(d,dim0,dim1); \
497 #endif /* !__STDC__ */
508 /* stop = hs->hs_stop; */
509 delay = hs->hs_delay;
510 if (stop && delay < 10000)
519 check_events (struct hyper_state *hs)
528 dpy = hs->hs_display;
529 count = XEventsQueued (dpy, QueuedAfterReading);
538 XNextEvent (dpy, &e);
547 case ConfigureNotify:
554 switch (e.xbutton.button)
557 hs->hs_stop = !hs->hs_stop;
570 screenhack_handle_event(dpy, &e);
575 resize = hs->hs_resize;
579 XWindowAttributes wa;
583 XGetWindowAttributes (dpy, win, &wa);
586 set_sizes (&hyper_state, width, height);
589 redraw = hs->hs_redraw;
591 XClearWindow (dpy, win);
596 set_sizes (struct hyper_state *hs, int width, int height)
605 observer_z = 0.5 * hs->hs_two_observer_z;
606 min_dim = width < height ? width : height;
607 var = sqrt(observer_z * observer_z - 1.0);
608 offset_x = 0.5 * (double)(width - 1);
609 offset_y = 0.5 * (double)(height - 1);
610 unit_scale = 0.4 * min_dim * var;
611 hs->hs_offset_x = (float)offset_x;
612 hs->hs_offset_y = (float)offset_y;
613 hs->hs_unit_scale = (float)unit_scale;
619 static const struct line_info line_table[LINE_COUNT] =