-/* xscreensaver, Copyright (c) 1992 Jamie Zawinski <jwz@lucid.com>
+/* xscreensaver, Copyright (c) 1992, 1995, 1996, 1998, 2000
+ * Jamie Zawinski <jwz@jwz.org>
*
* Permission to use, copy, modify, distribute, and sell this software and its
* documentation for any purpose is hereby granted without fee, provided that
* and Jamie Zawinski.
*/
-#include "screenhack.h"
#include <math.h>
+#include "screenhack.h"
-static Display *dpy;
-static Window window;
-static GC color0, color1, color2, color3, color4, color5, color6, color7;
-static GC black;
-
-static int delay;
+#define POINT_COUNT 16
+#define LINE_COUNT 32
-static int observer_z;
-static int x_offset, y_offset;
-static int unit_pixels;
+#define ANGLE_SCALE 0.001
-struct point_state {
- int old_x, old_y;
- int new_x, new_y;
- Bool same_p;
+struct line_info
+{
+ char li_ip;
+ char li_iq;
+ char li_color;
+ char li_pad;
};
-static void
-move_line (state0, state1, gc)
- struct point_state *state0, *state1;
- GC gc;
+struct point_state
{
- if (state0->same_p && state1->same_p)
- return;
- if (mono_p)
- {
- XDrawLine (dpy, window, black,
- state0->old_x, state0->old_y, state1->old_x, state1->old_y);
- XDrawLine (dpy, window, gc,
- state0->new_x, state0->new_y, state1->new_x, state1->new_y);
- }
- else
- {
- XSegment segments [2];
- segments [0].x1 = state0->old_x; segments [0].y1 = state0->old_y;
- segments [0].x2 = state1->old_x; segments [0].y2 = state1->old_y;
- segments [1].x1 = state0->new_x; segments [1].y1 = state0->new_y;
- segments [1].x2 = state1->new_x; segments [1].y2 = state1->new_y;
- XDrawSegments (dpy, window, gc, segments, 2);
- }
-}
+ short old_x, old_y;
+ short new_x, new_y;
+};
-static void
-hyper (xy, xz, yz, xw, yw, zw)
- double xy, xz, yz, xw, yw, zw;
+struct hyper_state
{
- double cos_xy = cos (xy), sin_xy = sin (xy);
- double cos_xz = cos (xz), sin_xz = sin (xz);
- double cos_yz = cos (yz), sin_yz = sin (yz);
- double cos_xw = cos (xw), sin_xw = sin (xw);
- double cos_yw = cos (yw), sin_yw = sin (yw);
- double cos_zw = cos (zw), sin_zw = sin (zw);
-
- double ax = 1.0, ay = 0.0, az = 0.0, aw = 0.0;
- double bx = 0.0, by = 1.0, bz = 0.0, bw = 0.0;
- double cx = 0.0, cy = 0.0, cz = 1.0, cw = 0.0;
- double dx = 0.0, dy = 0.0, dz = 0.0, dw = 1.0;
-
- double _tmp0_, _tmp1_;
-
- struct point_state points [16];
- memset (points, 0, sizeof (points));
-
-#define mmmm (&points[0])
-#define mmmp (&points[1])
-#define mmpm (&points[2])
-#define mmpp (&points[3])
-#define mpmm (&points[4])
-#define mpmp (&points[5])
-#define mppm (&points[6])
-#define mppp (&points[7])
-#define pmmm (&points[8])
-#define pmmp (&points[9])
-#define pmpm (&points[10])
-#define pmpp (&points[11])
-#define ppmm (&points[12])
-#define ppmp (&points[13])
-#define pppm (&points[14])
-#define pppp (&points[15])
-
- while (1)
- {
- double temp_mult;
-
-#define compute(a,b,c,d,point_state) \
- temp_mult = (unit_pixels / (((a*az) + (b*bz) + (c*cz) + (d*dz) + \
- (a*aw) + (b*bw) + (c*cw) + (d*dw)) \
- - observer_z)); \
- point_state->old_x = point_state->new_x; \
- point_state->old_y = point_state->new_y; \
- point_state->new_x = ((((a*ax) + (b*bx) + (c*cx) + (d*dx)) * temp_mult) \
- + x_offset); \
- point_state->new_y = ((((a*ay) + (b*by) + (c*cy) + (d*dy)) * temp_mult) \
- + y_offset); \
- point_state->same_p = (point_state->old_x == point_state->new_x && \
- point_state->old_y == point_state->new_y);
-
- compute (-1, -1, -1, -1, mmmm);
- compute (-1, -1, -1, 1, mmmp);
- compute (-1, -1, 1, -1, mmpm);
- compute (-1, -1, 1, 1, mmpp);
- compute (-1, 1, -1, -1, mpmm);
- compute (-1, 1, -1, 1, mpmp);
- compute (-1, 1, 1, -1, mppm);
- compute (-1, 1, 1, 1, mppp);
- compute ( 1, -1, -1, -1, pmmm);
- compute ( 1, -1, -1, 1, pmmp);
- compute ( 1, -1, 1, -1, pmpm);
- compute ( 1, -1, 1, 1, pmpp);
- compute ( 1, 1, -1, -1, ppmm);
- compute ( 1, 1, -1, 1, ppmp);
- compute ( 1, 1, 1, -1, pppm);
- compute ( 1, 1, 1, 1, pppp);
-
- move_line (mmmm, mmmp, color0);
- move_line (mmmm, mmpm, color0);
- move_line (mmpm, mmpp, color0);
- move_line (mmmp, mmpp, color0);
-
- move_line (pmmm, pmmp, color1);
- move_line (pmmm, pmpm, color1);
- move_line (pmpm, pmpp, color1);
- move_line (pmmp, pmpp, color1);
-
- move_line (mpmm, mpmp, color2);
- move_line (mpmm, mppm, color2);
- move_line (mppm, mppp, color2);
- move_line (mpmp, mppp, color2);
-
- move_line (mmpp, mppp, color3);
- move_line (mmpp, pmpp, color3);
- move_line (pmpp, pppp, color3);
- move_line (mppp, pppp, color3);
-
- move_line (mmmm, mpmm, color4);
- move_line (mmmm, pmmm, color4);
- move_line (mpmm, ppmm, color4);
- move_line (pmmm, ppmm, color4);
-
- move_line (mmmp, mpmp, color5);
- move_line (mmmp, pmmp, color5);
- move_line (pmmp, ppmp, color5);
- move_line (mpmp, ppmp, color5);
-
- move_line (mmpm, mppm, color6);
- move_line (mmpm, pmpm, color6);
- move_line (pmpm, pppm, color6);
- move_line (mppm, pppm, color6);
-
- move_line (ppmm, ppmp, color7);
- move_line (ppmm, pppm, color7);
- move_line (pppm, pppp, color7);
- move_line (ppmp, pppp, color7);
+ char hs_stop;
+ char hs_icon;
+ char hs_resize;
+ char hs_redraw;
+ Display *hs_display;
+ Window hs_window;
+ float hs_two_observer_z;
+ float hs_offset_x;
+ float hs_offset_y;
+ float hs_unit_scale;
+ int hs_delay;
+ GC hs_color_gcs[8];
+#if 0
+ double hs_angle_xy;
+ double hs_angle_xz;
+ double hs_angle_yz;
+ double hs_angle_xw;
+ double hs_angle_yw;
+ double hs_angle_zw;
+#endif
+ double hs_cos_xy, hs_sin_xy;
+ double hs_cos_xz, hs_sin_xz;
+ double hs_cos_yz, hs_sin_yz;
+ double hs_cos_xw, hs_sin_xw;
+ double hs_cos_yw, hs_sin_yw;
+ double hs_cos_zw, hs_sin_zw;
+ double hs_ref_ax, hs_ref_ay, hs_ref_az, hs_ref_aw;
+ double hs_ref_bx, hs_ref_by, hs_ref_bz, hs_ref_bw;
+ double hs_ref_cx, hs_ref_cy, hs_ref_cz, hs_ref_cw;
+ double hs_ref_dx, hs_ref_dy, hs_ref_dz, hs_ref_dw;
+ struct point_state hs_points[POINT_COUNT];
+};
- /* If you get error messages about the following forms, and you think you're
- using an ANSI C conforming compiler, then you're mistaken. Possibly you're
- mixing an ANSI compiler with a non-ANSI preprocessor, or vice versa.
- Regardless, your system is broken; it's not a bug in this program.
- */
-#if __STDC__
-# define rotate(name,dim0,dim1,cos,sin) \
- _tmp0_ = ((name##dim0 * cos) + (name##dim1 * sin)); \
- _tmp1_ = ((name##dim1 * cos) - (name##dim0 * sin)); \
- name##dim0 = _tmp0_; \
- name##dim1 = _tmp1_;
-
-# define rotates(dim0,dim1) \
- if (sin_##dim0##dim1 != 0) { \
- rotate(a, dim0, dim1, cos_##dim0##dim1, sin_##dim0##dim1); \
- rotate(b, dim0, dim1, cos_##dim0##dim1, sin_##dim0##dim1); \
- rotate(c, dim0, dim1, cos_##dim0##dim1, sin_##dim0##dim1); \
- rotate(d, dim0, dim1, cos_##dim0##dim1, sin_##dim0##dim1); \
- }
+static const struct line_info line_table[LINE_COUNT];
-#else /* !__STDC__, courtesy of Andreas Luik <luik@isa.de> */
-# define rotate(name,dim0,dim1,cos,sin) \
- _tmp0_ = ((name/**/dim0 * cos) + (name/**/dim1 * sin)); \
- _tmp1_ = ((name/**/dim1 * cos) - (name/**/dim0 * sin)); \
- name/**/dim0 = _tmp0_; \
- name/**/dim1 = _tmp1_;
-
-# define rotates(dim0,dim1) \
- if (sin_/**/dim0/**/dim1 != 0) { \
- rotate(a,dim0,dim1,cos_/**/dim0/**/dim1,sin_/**/dim0/**/dim1); \
- rotate(b,dim0,dim1,cos_/**/dim0/**/dim1,sin_/**/dim0/**/dim1); \
- rotate(c,dim0,dim1,cos_/**/dim0/**/dim1,sin_/**/dim0/**/dim1); \
- rotate(d,dim0,dim1,cos_/**/dim0/**/dim1,sin_/**/dim0/**/dim1); \
- }
-#endif /* !__STDC__ */
+static void init (struct hyper_state *hs);
+static void hyper (struct hyper_state *hs);
+static void check_events (struct hyper_state *hs);
+static void set_sizes (struct hyper_state *hs, int width, int height);
- rotates (x,y);
- rotates (x,z);
- rotates (y,z);
- rotates (x,w);
- rotates (y,w);
- rotates (z,w);
+static struct hyper_state hyper_state;
- XSync (dpy, True);
- if (delay) usleep (delay);
- }
-}
-\f
char *progclass = "Hypercube";
-char *defaults [] = {
- "*background: black",
- "*foreground: white",
- "*color0: red",
- "*color1: orange",
- "*color2: yellow",
- "*color3: white",
+char *defaults[] =
+{
+ "*observer-z: 3",
+ "*delay: 10000",
+ "*xy: 3",
+ "*xz: 5",
+ "*yw: 10",
+ "*yz: 0",
+ "*xw: 0",
+ "*zw: 0",
+ ".background: black",
+ ".foreground: white",
+ "*color0: magenta",
+ "*color3: #FF0093",
+ "*color1: yellow",
+ "*color2: #FF9300",
"*color4: green",
- "*color5: cyan",
- "*color6: dodgerblue",
- "*color7: magenta",
-
- "*xw: 0.000",
- "*xy: 0.010",
- "*xz: 0.005",
- "*yw: 0.010",
- "*yz: 0.000",
- "*zw: 0.000",
-
- "*observer-z: 5",
- "*delay: 100000",
+ "*color7: #00FFD0",
+ "*color5: #8080FF",
+ "*color6: #00D0FF",
+
0
};
-XrmOptionDescRec options [] = {
+XrmOptionDescRec options [] =
+{
{ "-color0", ".color0", XrmoptionSepArg, 0 },
{ "-color1", ".color1", XrmoptionSepArg, 0 },
{ "-color2", ".color2", XrmoptionSepArg, 0 },
{ "-zw", ".zw", XrmoptionSepArg, 0 },
{ "-observer-z", ".observer-z", XrmoptionSepArg, 0 },
- { "-delay", ".delay", XrmoptionSepArg, 0 }
+ { "-delay", ".delay", XrmoptionSepArg, 0 },
+ { 0, 0, 0, 0 }
};
-int options_size = (sizeof (options) / sizeof (options[0]));
-
void
-screenhack (d, w)
- Display *d;
- Window w;
+screenhack (Display *d, Window w)
{
- XGCValues gcv;
- XWindowAttributes xgwa;
- Colormap cmap;
- double xy, xz, yz, xw, yw, zw;
- unsigned long bg, pixel;
+ struct hyper_state *hs;
- dpy = d;
- window = w;
- XGetWindowAttributes (dpy, window, &xgwa);
- cmap = xgwa.colormap;
+ hs = &hyper_state;
+ hs->hs_display = d;
+ hs->hs_window = w;
- x_offset = xgwa.width / 2;
- y_offset = xgwa.height / 2;
- unit_pixels = xgwa.width < xgwa.height ? xgwa.width : xgwa.height;
+ init (hs);
- xy = get_float_resource ("xy", "Float");
- xz = get_float_resource ("xz", "Float");
- yz = get_float_resource ("yz", "Float");
- xw = get_float_resource ("xw", "Float");
- yw = get_float_resource ("yw", "Float");
- zw = get_float_resource ("zw", "Float");
+ hyper (hs);
+}
- observer_z = get_integer_resource ("observer-z", "Integer");
+
+static void
+init (struct hyper_state *hs)
+{
+ Display *dpy;
+ Window win;
+ XGCValues gcv;
+ Colormap cmap;
+ unsigned long bg_pixel;
+ int delay;
+ float observer_z;
+
+ dpy = hs->hs_display;
+ win = hs->hs_window;
+
+ observer_z = get_float_resource ("observer-z", "Float");
+ if (observer_z < 1.125)
+ observer_z = 1.125;
+ /* hs->hs_observer_z = observer_z; */
+ hs->hs_two_observer_z = 2.0 * observer_z;
+
+ {
+ int root;
+ XWindowAttributes wa;
+ int width;
+ int height;
+
+ root = get_boolean_resource("root", "Boolean");
+ XGetWindowAttributes (dpy, win, &wa);
+ XSelectInput(dpy, win, root ? ExposureMask :
+ wa.your_event_mask | ExposureMask |
+ ButtonPressMask | StructureNotifyMask);
+
+ width = wa.width;
+ height = wa.height;
+ cmap = wa.colormap;
+ set_sizes (hs, width, height);
+ }
delay = get_integer_resource ("delay", "Integer");
+ hs->hs_delay = delay;
- bg = get_pixel_resource ("background", "Background", dpy, cmap);
+ bg_pixel = get_pixel_resource ("background", "Background", dpy, cmap);
if (mono_p)
{
+ GC black_gc;
+ unsigned long fg_pixel;
+ GC white_gc;
+
gcv.function = GXcopy;
- gcv.foreground = bg;
- black = XCreateGC (dpy, window, GCForeground|GCFunction, &gcv);
- gcv.foreground = get_pixel_resource ("foreground", "Foreground",
- dpy, cmap);
- color0 = color1 = color2 = color3 = color4 = color5 = color6 = color7 =
- XCreateGC (dpy, window, GCForeground|GCFunction, &gcv);
+ gcv.foreground = bg_pixel;
+ black_gc = XCreateGC (dpy, win, GCForeground|GCFunction, &gcv);
+ fg_pixel = get_pixel_resource ("foreground", "Foreground", dpy, cmap);
+ gcv.foreground = fg_pixel ^ bg_pixel;
+ white_gc = XCreateGC (dpy, win, GCForeground|GCFunction, &gcv);
+ hs->hs_color_gcs[0] = black_gc;
+ hs->hs_color_gcs[1] = white_gc;
}
else
{
- black = 0;
+ int col;
+
gcv.function = GXxor;
-#define make_gc(color,name) \
- gcv.foreground = bg ^ get_pixel_resource ((name), "Foreground", \
- dpy, cmap); \
- color = XCreateGC (dpy, window, GCForeground|GCFunction, &gcv)
-
- make_gc (color0,"color0");
- make_gc (color1,"color1");
- make_gc (color2,"color2");
- make_gc (color3,"color3");
- make_gc (color4,"color4");
- make_gc (color5,"color5");
- make_gc (color6,"color6");
- make_gc (color7,"color7");
+ for (col = 0; col < 8; col++)
+ {
+ char buffer[16];
+ unsigned long fg_pixel;
+ GC color_gc;
+
+ sprintf (buffer, "color%d", col);
+ fg_pixel = get_pixel_resource (buffer, "Foreground", dpy, cmap);
+ gcv.foreground = fg_pixel ^ bg_pixel;
+ color_gc = XCreateGC (dpy, win, GCForeground|GCFunction, &gcv);
+ hs->hs_color_gcs[col] = color_gc;
+ }
+ }
+
+ hs->hs_ref_ax = 1.0, hs->hs_ref_ay = 0.0, hs->hs_ref_az = 0.0, hs->hs_ref_aw = 0.0;
+ hs->hs_ref_bx = 0.0, hs->hs_ref_by = 1.0, hs->hs_ref_bz = 0.0, hs->hs_ref_bw = 0.0;
+ hs->hs_ref_cx = 0.0, hs->hs_ref_cy = 0.0, hs->hs_ref_cz = 1.0, hs->hs_ref_cw = 0.0;
+ hs->hs_ref_dx = 0.0, hs->hs_ref_dy = 0.0, hs->hs_ref_dz = 0.0, hs->hs_ref_dw = 1.0;
+
+ {
+ double xy;
+ double xz;
+ double yz;
+ double xw;
+ double yw;
+ double zw;
+ double cos_xy, sin_xy;
+ double cos_xz, sin_xz;
+ double cos_yz, sin_yz;
+ double cos_xw, sin_xw;
+ double cos_yw, sin_yw;
+ double cos_zw, sin_zw;
+
+ xy = get_float_resource ("xy", "Float") * ANGLE_SCALE;
+ xz = get_float_resource ("xz", "Float") * ANGLE_SCALE;
+ yz = get_float_resource ("yz", "Float") * ANGLE_SCALE;
+ xw = get_float_resource ("xw", "Float") * ANGLE_SCALE;
+ yw = get_float_resource ("yw", "Float") * ANGLE_SCALE;
+ zw = get_float_resource ("zw", "Float") * ANGLE_SCALE;
+
+ cos_xy = cos (xy), sin_xy = sin (xy);
+ hs->hs_cos_xy = cos_xy, hs->hs_sin_xy = sin_xy;
+ cos_xz = cos (xz), sin_xz = sin (xz);
+ hs->hs_cos_xz = cos_xz, hs->hs_sin_xz = sin_xz;
+ cos_yz = cos (yz), sin_yz = sin (yz);
+ hs->hs_cos_yz = cos_yz, hs->hs_sin_yz = sin_yz;
+ cos_xw = cos (xw), sin_xw = sin (xw);
+ hs->hs_cos_xw = cos_xw, hs->hs_sin_xw = sin_xw;
+ cos_yw = cos (yw), sin_yw = sin (yw);
+ hs->hs_cos_yw = cos_yw, hs->hs_sin_yw = sin_yw;
+ cos_zw = cos (zw), sin_zw = sin (zw);
+ hs->hs_cos_zw = cos_zw, hs->hs_sin_zw = sin_zw;
+ }
+}
+
+
+static void
+hyper (struct hyper_state *hs)
+{
+ int roted;
+
+ roted = 0;
+
+ for (;;)
+ {
+ int icon;
+ int resize;
+ char moved[POINT_COUNT];
+ int redraw;
+ int stop;
+ int delay;
+
+ check_events (hs);
+
+ icon = hs->hs_icon;
+ resize = hs->hs_resize;
+ if (icon || !(roted | resize))
+ goto skip1;
+
+ {
+ float observer_z;
+ float unit_scale;
+ float offset_x;
+ float offset_y;
+ double az, bz, cz, dz;
+ double sum_z;
+ double ax, bx, cx, dx;
+ double sum_x;
+ double ay, by, cy, dy;
+ double sum_y;
+ struct point_state *ps;
+ int old_x;
+ int old_y;
+ double mul;
+ double xf;
+ double yf;
+ int new_x;
+ int new_y;
+ int mov;
+
+
+#define compute(as,bs,cs,ds,i) \
+ az = hs->hs_ref_az; bz = hs->hs_ref_bz; cz = hs->hs_ref_cz; dz = hs->hs_ref_dz; \
+ ax = hs->hs_ref_ax; bx = hs->hs_ref_bx; cx = hs->hs_ref_cx; dx = hs->hs_ref_dx; \
+ ay = hs->hs_ref_ay; by = hs->hs_ref_by; cy = hs->hs_ref_cy; dy = hs->hs_ref_dy; \
+ sum_z = as az bs bz cs cz ds dz; \
+ observer_z = hs->hs_two_observer_z; \
+ unit_scale = hs->hs_unit_scale; \
+ sum_x = as ax bs bx cs cx ds dx; \
+ sum_y = as ay bs by cs cy ds dy; \
+ ps = &hs->hs_points[i]; \
+ mul = unit_scale / (observer_z - sum_z); \
+ offset_x = hs->hs_offset_x; \
+ offset_y = hs->hs_offset_y; \
+ old_x = ps->new_x; \
+ old_y = ps->new_y; \
+ xf = sum_x * mul + offset_x; \
+ yf = sum_y * mul + offset_y; \
+ new_x = (int)rint(xf); \
+ new_y = (int)rint(yf); \
+ ps->old_x = old_x; \
+ ps->old_y = old_y; \
+ ps->new_x = new_x; \
+ ps->new_y = new_y; \
+ mov = old_x != new_x || old_y != new_y; \
+ moved[i] = mov;
+
+ compute (-, -, -, -, 0);
+ compute (-, -, -, +, 1);
+ compute (-, -, +, -, 2);
+ compute (-, -, +, +, 3);
+ compute (-, +, -, -, 4);
+ compute (-, +, -, +, 5);
+ compute (-, +, +, -, 6);
+ compute (-, +, +, +, 7);
+ compute (+, -, -, -, 8);
+ compute (+, -, -, +, 9);
+ compute (+, -, +, -, 10);
+ compute (+, -, +, +, 11);
+ compute (+, +, -, -, 12);
+ compute (+, +, -, +, 13);
+ compute (+, +, +, -, 14);
+ compute (+, +, +, +, 15);
+ }
+
+ skip1:
+ icon = hs->hs_icon;
+ redraw = hs->hs_redraw;
+ if (icon || !(roted | redraw))
+ goto skip2;
+
+ {
+ int lc;
+ const struct line_info *lip;
+ int mono;
+ Display *dpy;
+ Window win;
+
+ lc = LINE_COUNT;
+ lip = &line_table[0];
+ mono = mono_p;
+ dpy = hs->hs_display;
+ win = hs->hs_window;
+
+ while (--lc >= 0)
+ {
+ int ip;
+ int iq;
+ int col;
+ struct point_state *sp;
+ struct point_state *sq;
+ int mov_p;
+ int mov_q;
+ GC erase_gc;
+ GC draw_gc;
+ int p_x;
+ int p_y;
+ int q_x;
+ int q_y;
+
+ ip = lip->li_ip;
+ iq = lip->li_iq;
+ col = lip->li_color;
+ lip++;
+ mov_p = moved[ip];
+ mov_q = moved[iq];
+ if (!(redraw | mov_p | mov_q))
+ continue;
+
+ sp = &hs->hs_points[ip];
+ sq = &hs->hs_points[iq];
+
+ if (mono)
+ {
+ erase_gc = hs->hs_color_gcs[0];
+ draw_gc = hs->hs_color_gcs[1];
+ }
+ else
+ {
+ GC color_gc;
+
+ color_gc = hs->hs_color_gcs[col];
+ erase_gc = color_gc;
+ draw_gc = color_gc;
+ }
+
+ if (!redraw)
+ {
+ p_x = sp->old_x;
+ p_y = sp->old_y;
+ q_x = sq->old_x;
+ q_y = sq->old_y;
+ XDrawLine (dpy, win, erase_gc, p_x, p_y, q_x, q_y);
+ }
+
+ p_x = sp->new_x;
+ p_y = sp->new_y;
+ q_x = sq->new_x;
+ q_y = sq->new_y;
+ XDrawLine (dpy, win, draw_gc, p_x, p_y, q_x, q_y);
+ }
+
+ XFlush (dpy);
+ }
+
+ skip2:
+ stop = hs->hs_stop;
+ roted = 0;
+ if (stop)
+ goto skip3;
+
+ roted = 1;
+
+ {
+ double cos_a;
+ double sin_a;
+ double old_u;
+ double old_v;
+ double new_u;
+ double new_v;
+
+ /* If you get error messages about the following forms, and you think you're
+ using an ANSI C conforming compiler, then you're mistaken. Possibly you're
+ mixing an ANSI compiler with a non-ANSI preprocessor, or vice versa.
+ Regardless, your system is broken; it's not a bug in this program.
+ */
+#if defined(__STDC__) || defined(__ANSI_CPP__)
+
+#define rotate(name,dim0,dim1) \
+ old_u = hs->hs_ref_##name##dim0; \
+ old_v = hs->hs_ref_##name##dim1; \
+ new_u = old_u * cos_a + old_v * sin_a; \
+ new_v = old_v * cos_a - old_u * sin_a; \
+ hs->hs_ref_##name##dim0 = new_u; \
+ hs->hs_ref_##name##dim1 = new_v;
+
+#define rotates(dim0,dim1) \
+ if (hs->hs_sin_##dim0##dim1 != 0) { \
+ cos_a = hs->hs_cos_##dim0##dim1; \
+ sin_a = hs->hs_sin_##dim0##dim1; \
+ rotate(a,dim0,dim1); \
+ rotate(b,dim0,dim1); \
+ rotate(c,dim0,dim1); \
+ rotate(d,dim0,dim1); \
+ }
+
+#else /* !__STDC__, courtesy of Andreas Luik <luik@isa.de> */
+
+#define rotate(name,dim0,dim1) \
+ old_u = hs->hs_ref_/**/name/**/dim0; \
+ old_v = hs->hs_ref_/**/name/**/dim1; \
+ new_u = old_u * cos_a + old_v * sin_a; \
+ new_v = old_v * cos_a - old_u * sin_a; \
+ hs->hs_ref_/**/name/**/dim0 = new_u; \
+ hs->hs_ref_/**/name/**/dim1 = new_v;
+
+#define rotates(dim0,dim1) \
+ if (hs->hs_sin_/**/dim0/**/dim1 != 0) { \
+ cos_a = hs->hs_cos_/**/dim0/**/dim1; \
+ sin_a = hs->hs_sin_/**/dim0/**/dim1; \
+ rotate(a,dim0,dim1); \
+ rotate(b,dim0,dim1); \
+ rotate(c,dim0,dim1); \
+ rotate(d,dim0,dim1); \
+ }
+
+#endif /* !__STDC__ */
+
+ rotates (x,y);
+ rotates (x,z);
+ rotates (y,z);
+ rotates (x,w);
+ rotates (y,w);
+ rotates (z,w);
+ }
+
+ skip3:
+ /* stop = hs->hs_stop; */
+ delay = hs->hs_delay;
+ if (stop && delay < 10000)
+ delay = 10000;
+ if (delay > 0)
+ usleep (delay);
+ }
+}
+
+
+static void
+check_events (struct hyper_state *hs)
+{
+ Display *dpy;
+ int count;
+ int ic;
+ int resize;
+ Window win;
+ int redraw;
+
+ dpy = hs->hs_display;
+ count = XEventsQueued (dpy, QueuedAfterReading);
+ ic = count;
+ hs->hs_resize = 0;
+ hs->hs_redraw = 0;
+
+ while (--ic >= 0)
+ {
+ XEvent e;
+
+ XNextEvent (dpy, &e);
+
+ switch (e.type)
+ {
+ case Expose:
+ hs->hs_icon = 0;
+ hs->hs_redraw = 1;
+ break;
+
+ case ConfigureNotify:
+ hs->hs_icon = 0;
+ hs->hs_resize = 1;
+ hs->hs_redraw = 1;
+ break;
+
+ case ButtonPress:
+ switch (e.xbutton.button)
+ {
+ case 2:
+ hs->hs_stop = !hs->hs_stop;
+ break;
+ default:
+ break;
+ }
+ break;
+
+ case UnmapNotify:
+ hs->hs_icon = 1;
+ hs->hs_redraw = 0;
+ break;
+
+ default:
+ screenhack_handle_event(dpy, &e);
+ break;
+ }
+ }
+
+ resize = hs->hs_resize;
+ win = hs->hs_window;
+ if (resize)
+ {
+ XWindowAttributes wa;
+ int width;
+ int height;
+
+ XGetWindowAttributes (dpy, win, &wa);
+ width = wa.width;
+ height = wa.height;
+ set_sizes (&hyper_state, width, height);
}
- hyper (xy, xz, yz, xw, yw, zw);
+ redraw = hs->hs_redraw;
+ if (redraw)
+ XClearWindow (dpy, win);
}
+
+
+static void
+set_sizes (struct hyper_state *hs, int width, int height)
+{
+ double observer_z;
+ int min_dim;
+ double var;
+ double offset_x;
+ double offset_y;
+ double unit_scale;
+
+ observer_z = 0.5 * hs->hs_two_observer_z;
+ min_dim = width < height ? width : height;
+ var = sqrt(observer_z * observer_z - 1.0);
+ offset_x = 0.5 * (double)(width - 1);
+ offset_y = 0.5 * (double)(height - 1);
+ unit_scale = 0.4 * min_dim * var;
+ hs->hs_offset_x = (float)offset_x;
+ hs->hs_offset_y = (float)offset_y;
+ hs->hs_unit_scale = (float)unit_scale;
+}
+
+
+/* data */
+
+static const struct line_info line_table[LINE_COUNT] =
+{
+ { 0, 1, 0, },
+ { 0, 2, 0, },
+ { 1, 3, 0, },
+ { 2, 3, 0, },
+ { 4, 5, 1, },
+ { 4, 6, 1, },
+ { 5, 7, 1, },
+ { 6, 7, 1, },
+ { 0, 4, 4, },
+ { 0, 8, 4, },
+ { 4, 12, 4, },
+ { 8, 12, 4, },
+ { 1, 5, 5, },
+ { 1, 9, 5, },
+ { 5, 13, 5, },
+ { 9, 13, 5, },
+ { 2, 6, 6, },
+ { 2, 10, 6, },
+ { 6, 14, 6, },
+ { 10, 14, 6, },
+ { 3, 7, 7, },
+ { 3, 11, 7, },
+ { 7, 15, 7, },
+ { 11, 15, 7, },
+ { 8, 9, 2, },
+ { 8, 10, 2, },
+ { 9, 11, 2, },
+ { 10, 11, 2, },
+ { 12, 13, 3, },
+ { 12, 14, 3, },
+ { 13, 15, 3, },
+ { 14, 15, 3, },
+};
+