import java.awt.*; import java.awt.image.*; import kinetoscope.awt.*; /** * * * This is a Java port of hypercube by jwz@jwz.org, which is included in * xscreensaver. *

* This is the original copyright notice in jwz's C source: *

 * xscreensaver, Copyright (c) 1992, 1995, 1996, 1998
 *  Jamie Zawinski 
 *
 * Permission to use, copy, modify, distribute, and sell this software and its
 * documentation for any purpose is hereby granted without fee, provided that
 * the above copyright notice appear in all copies and that both that
 * copyright notice and this permission notice appear in supporting
 * documentation.  No representations are made about the suitability of this
 * software for any purpose.  It is provided "as is" without express or 
 * implied warranty.
 *
 * This code derived from TI Explorer Lisp code by Joe Keane, Fritz Mueller,
 * and Jamie Zawinski.
 * 
* * */ public class HyperCube extends DoubleBufferedFrame implements Runnable { public static long kRefreshInterval = 30; private Thread refreshThread; int width, height; boolean firstPaint = false; /* These are the global variables and other vars from hyper() function in hypercube.c */ double observer_z; double x_offset, y_offset; double unit_pixels; double cos_xy; double cos_xz; double cos_yz; double cos_xw; double cos_yw; double cos_zw; double sin_xy; double sin_xz; double sin_yz; double sin_xw; double sin_yw; double sin_zw; double xy; double xz; double yz; double xw; double yw; double 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; Color color0; Color color1; Color color2; Color color3; Color color4; Color color5; Color color6; Color color7; PointState[] points; boolean mono_p; /* This is essentially the screenhack() function from hypercube.c */ public HyperCube(String[] args) { super("COLOR FRAME"); setSize(512, 384); initFrame(); Options options = new Options(args); mono_p = options.mono; kRefreshInterval = options.delay; observer_z = options.observer_z; this.xy = options.xy; this.xz = options.xz; this.yz = options.yz; this.xw = options.xw; this.yw = options.yw; this.zw = options.zw; cos_xy = cos(this.xy); cos_xz = cos(this.xz); cos_yz = cos(this.yz); cos_xw = cos(this.xw); cos_yw = cos(this.yw); cos_zw = cos(this.zw); sin_xy = sin(this.xy); sin_xz = sin(this.xz); sin_yz = sin(this.yz); sin_xw = sin(this.xw); sin_yw = sin(this.yw); sin_zw = sin(this.zw); points = new PointState[16]; if(mono_p) { color0 = Color.white; color1 = Color.white; color2 = Color.white; color3 = Color.white; color4 = Color.white; color5 = Color.white; color6 = Color.white; color7 = Color.white; } else { color0 = Color.white; color1 = Color.cyan; color2 = Color.red; color3 = Color.green; color4 = Color.blue; color5 = Color.magenta; color6 = Color.yellow; color7 = Color.pink; } for(int i=0;i<16;i++) { points[i] = new PointState(); } refreshThread = new Thread(this); refreshThread.setPriority(Thread.MIN_PRIORITY); refreshThread.start(); this.show(); } /* This is the hyper() function from hypercube.c which does the calculations and draws the lines */ synchronized void hyper(Graphics g) { compute (-1, -1, -1, -1, points[0]); compute (-1, -1, -1, 1, points[1]); compute (-1, -1, 1, -1, points[2]); compute (-1, -1, 1, 1, points[3]); compute (-1, 1, -1, -1, points[4]); compute (-1, 1, -1, 1, points[5]); compute (-1, 1, 1, -1, points[6]); compute (-1, 1, 1, 1, points[7]); compute ( 1, -1, -1, -1, points[8]); compute ( 1, -1, -1, 1, points[9]); compute ( 1, -1, 1, -1, points[10]); compute ( 1, -1, 1, 1, points[11]); compute ( 1, 1, -1, -1, points[12]); compute ( 1, 1, -1, 1, points[13]); compute ( 1, 1, 1, -1, points[14]); compute ( 1, 1, 1, 1, points[15]); move_line (points[0], points[1], color0, g); move_line (points[0], points[2], color0, g); move_line (points[2], points[3], color0, g); move_line (points[1], points[3], color0, g); move_line (points[8], points[9], color1, g); move_line (points[8], points[10], color1, g); move_line (points[10], points[11], color1, g); move_line (points[9], points[11], color1, g); move_line (points[4], points[5], color2, g); move_line (points[4], points[6], color2, g); move_line (points[6], points[7], color2, g); move_line (points[5], points[7], color2, g); move_line (points[3], points[7], color3, g); move_line (points[3], points[11], color3, g); move_line (points[11], points[15], color3, g); move_line (points[7], points[15], color3, g); move_line (points[0], points[4], color4, g); move_line (points[0], points[8], color4, g); move_line (points[4], points[12], color4, g); move_line (points[8], points[12], color4, g); move_line (points[1], points[5], color5, g); move_line (points[1], points[9], color5, g); move_line (points[9], points[13], color5, g); move_line (points[5], points[13], color5, g); move_line (points[2], points[6], color6, g); move_line (points[2], points[10], color6, g); move_line (points[10], points[14], color6, g); move_line (points[6], points[14], color6, g); move_line (points[12], points[13], color7, g); move_line (points[12], points[14], color7, g); move_line (points[14], points[15], color7, g); move_line (points[13], points[15], color7, g); rotateXY(); rotateXZ(); rotateYZ(); rotateXW(); rotateYW(); rotateZW(); } /* This mimics move_line() in hypercube.c */ void move_line(PointState state0, PointState state1, Color gc, Graphics X) { if(state0.same_p && state1.same_p) { return; } if(mono_p) { X.setColor(new Color(0,0,0)); X.drawLine(state0.old_x, state0.old_y, state1.old_x, state1.old_y); X.setColor(gc); X.drawLine(state0.new_x, state0.new_y, state1.new_x, state1.new_y); } else { X.setColor(gc); // X.drawLine(state0.old_x, state0.old_y, state1.old_x, state1.old_y); X.drawLine(state0.new_x, state0.new_y, state1.new_x, state1.new_y); } } /* This accomplishes the same task as the compute() #define in hypercube.c */ void compute(double a, double b, double c, double d, PointState point_state) { double temp_mult = ((unit_pixels+0.0) / (((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 = (int)Math.round((double)((((a*ax) + (b*bx) + (c*cx) + (d*dx)) * temp_mult) + x_offset)); point_state.new_y = (int)Math.round((double)((((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); } /* This attempts to mimic the rotate() and rotates() #defines in hypercube.c without concatenating variable names "##" */ double rotate0(double dim0, double dim1, double cos, double sin) { return((dim0 * cos) + (dim1 * sin)); } double rotate1(double dim0, double dim1, double cos, double sin) { return((dim1 * cos) - (dim0 * sin)); } /* this is the enumeration of rotates() #define */ void rotateXY() { double tmp; if(sin_xy != 0) { tmp = rotate0(ax, ay, cos_xy, sin_xy); ay = rotate1(ax, ay, cos_xy, sin_xy); ax = tmp; tmp = rotate0(bx, by, cos_xy, sin_xy); by = rotate1(bx, by, cos_xy, sin_xy); bx = tmp; tmp = rotate0(cx, cy, cos_xy, sin_xy); cy = rotate1(cx, cy, cos_xy, sin_xy); cx = tmp; tmp = rotate0(dx, dy, cos_xy, sin_xy); dy = rotate1(dx, dy, cos_xy, sin_xy); dx = tmp; } } void rotateXZ() { double tmp; if(sin_xz != 0) { tmp = rotate0(ax, az, cos_xz, sin_xz); az = rotate1(ax, az, cos_xz, sin_xz); ax = tmp; tmp = rotate0(bx, bz, cos_xz, sin_xz); bz = rotate1(bx, bz, cos_xz, sin_xz); bx = tmp; tmp = rotate0(cx, cz, cos_xz, sin_xz); cz = rotate1(cx, cz, cos_xz, sin_xz); cx = tmp; tmp = rotate0(dx, dz, cos_xz, sin_xz); dz = rotate1(dx, dz, cos_xz, sin_xz); dx = tmp; } } void rotateYZ() { double tmp; if(sin_yz != 0) { tmp = rotate0(ay, az, cos_yz, sin_yz); az = rotate1(ay, az, cos_yz, sin_yz); ay = tmp; tmp = rotate0(by, bz, cos_yz, sin_yz); bz = rotate1(by, bz, cos_yz, sin_yz); by = tmp; tmp = rotate0(cy, cz, cos_yz, sin_yz); cz = rotate1(cy, cz, cos_yz, sin_yz); cy = tmp; tmp = rotate0(dy, dz, cos_yz, sin_yz); dz = rotate1(dy, dz, cos_yz, sin_yz); dy = tmp; } } void rotateXW() { double tmp; if(sin_xw != 0) { tmp = rotate0(ax, aw, cos_xw, sin_xw); aw = rotate1(ax, aw, cos_xw, sin_xw); ax = tmp; tmp = rotate0(bx, bw, cos_xw, sin_xw); bw = rotate1(bx, bw, cos_xw, sin_xw); bx = tmp; tmp = rotate0(cx, cw, cos_xw, sin_xw); cw = rotate1(cx, cw, cos_xw, sin_xw); cx = tmp; tmp = rotate0(dx, dw, cos_xw, sin_xw); dw = rotate1(dx, dw, cos_xw, sin_xw); dx = tmp; } } void rotateYW() { double tmp; if(sin_yw != 0) { tmp = rotate0(ay, aw, cos_yw, sin_yw); aw = rotate1(ay, aw, cos_yw, sin_yw); ay = tmp; tmp = rotate0(by, bw, cos_yw, sin_yw); bw = rotate1(by, bw, cos_yw, sin_yw); by = tmp; tmp = rotate0(cy, cw, cos_yw, sin_yw); cw = rotate1(cy, cw, cos_yw, sin_yw); cy = tmp; tmp = rotate0(dy, dw, cos_yw, sin_yw); dw = rotate1(dy, dw, cos_yw, sin_yw); dy = tmp; } } void rotateZW() { double tmp; if(sin_zw != 0) { tmp = rotate0(az, aw, cos_zw, sin_zw); aw = rotate1(az, aw, cos_zw, sin_zw); az = tmp; tmp = rotate0(bz, bw, cos_zw, sin_zw); bw = rotate1(bz, bw, cos_zw, sin_zw); bz = tmp; tmp = rotate0(cz, cw, cos_zw, sin_zw); cw = rotate1(cz, cw, cos_zw, sin_zw); cz = tmp; tmp = rotate0(dz, dw, cos_zw, sin_zw); dw = rotate1(dz, dw, cos_zw, sin_zw); dz = tmp; } } /* This is the point_state struct in hypercube.c */ public class PointState { public int old_x; public int old_y; public int new_x; public int new_y; public boolean same_p; PointState() { old_x=0; old_y=0; new_x=0; new_y=0; same_p=true; } } /*** These are shortcuts used for accessing static methods in java.lang.Math **/ double cos(double x) {return(Math.cos(x));} double sin(double x) {return(Math.sin(x));} /*** These methods are DoubleBufferedFrame methods ***/ public void initFrame() { width = getSize().width; height = getSize().height; setBackground(new Color(0,0,0)); } public void paintContent(Graphics g, int width, int height) { if((this.width!=width || this.height!=height) || firstPaint) { x_offset = (width / 2); y_offset = (height / 2); unit_pixels = (width < height) ? width : height; this.width = width; this.height = height; firstPaint = false; } hyper(g); } public void run() { firstPaint = true; while (true) { repaint(); try { Thread.sleep(kRefreshInterval); } catch (InterruptedException e) { ; } } } /*** This is the command line part */ public class Options { double xy = .005; double xz = .005; double yz = .005; double xw = .005; double yw = .005; double zw = .005; double observer_z = 5; int delay = 30; boolean mono = false; Options(String[] args) { try { for(int x=0;x"); System.out.println(" -xz "); System.out.println(" -yz "); System.out.println(" -xw "); System.out.println(" -yw "); System.out.println(" -zw "); System.out.println(" -delay "); System.out.println(" -observer_z "); System.out.println(" -mono"); System.exit(-1); } } } public static void main(String[] argv) { HyperCube frame = new HyperCube(argv); } }